/**
 * Copyright 2017 orivil Authors. All rights reserved.
 * Use of this source code is governed by a MIT-style
 * license that can be found at https://mit-license.org.
 */

package swagger

import (
	"reflect"
	"gitee.com/tugoer/param"
)

// The name of the property corresponds to the name of the header.
// The value describes the type of the header.
type Headers map[string]*Header

type Header struct {
	// A short description of the header.
	Description string `json:"description,omitempty"`

	// Required.
	// The type of the object. The value MUST be one of
	// "string", "number", "integer", "boolean", or "array".
	Type string `json:"type,omitempty"`

	// The extending format for the previously mentioned type.
	// See Data Type Formats(http://swagger.io/specification/#dataTypeFormat) for further details.
	Format string `json:"format,omitempty"`

	// Required if type is "array". Describes the type of items in the array.
	Items *Items `json:"items,omitempty"`

	// Determines the format of the array if type array is used. Possible values are:
	//	csv - comma separated values foo,bar.
	//	ssv - space separated values foo bar.
	//	tsv - tab separated values foo\bar.
	//	pipes - pipe separated values foo|bar.
	// Default value is csv.
	CollectionFormat string `json:"collectionFormat,omitempty"`

	// Declares the value of the header that the server will use if none is provided.
	// (Note: "default" has no meaning for required headers.)
	// See https://tools.ietf.org/html/draft-fge-json-schema-validation-00#section-6.2.
	// Unlike JSON Schema this value MUST conform to the defined type for the header.
	Default interface{} `json:"default,omitempty"`

	*Validation
}

func (h *Header) setDataType(typ, format string, items *Items) {
	h.Type = typ
	h.Format = format
	h.Items = items
}

// TODO: test NewResponseHeaders
func NewResponseHeaders(schemas ...interface{}) Headers {
	var headers = make(Headers, len(schemas))
	for _, schema := range schemas {
		rt := param.ReflectTypeOf(schema, nil, nil)
		rt.Range(func(kind reflect.Kind, field reflect.StructField, pvd param.ConditionProvider) {
			header := &Header{}
			setDataType(kind, header)
			headers[field.Name] = header
			tag := field.Tag
			format := tag.Get("format")
			if format != "" {
				header.Format = format
			}
			typ := tag.Get("type")
			if typ != "" {
				header.Type = typ
			}
			header.Description += tag.Get("desc")
		})
	}
	return headers
}